<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>生产者消费者问题</title>
  <style>
    :root {
      --producer-color: #3498db;
      --consumer-color: #e74c3c;
      --buffer-color: #2ecc71;
      --history-bg: #f8f9fa;
    }

    body {
      font-family: 'Segoe UI', Arial, sans-serif;
      background: #f5f6fa;
      display: flex;
      flex-direction: column;
      align-items: center;
      min-height: 100vh;
      margin: 0;
      padding: 20px;
    }

    .dashboard {
      display: flex;
      gap: 30px;
      margin: 40px 0;
    }

    .status-card {
      width: 320px;
      height: 320px;
      background: white;
      border-radius: 16px;
      box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
      padding: 20px;
      position: relative;
      overflow: hidden;
      transition: transform 0.3s;
    }

    .status-card:hover {
      transform: translateY(-5px);
    }

    .status-header {
      font-size: 1.2em;
      color: #666;
      margin-bottom: 15px;
    }

    .status-content {
      position: relative;
      height: 180px;
    }

    .action-icon {
      width: 160px;
      height: 160px;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      opacity: 0;
      transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .producer .action-icon {
      filter: drop-shadow(0 4px 6px rgba(52, 152, 219, 0.3));
    }

    .consumer .action-icon {
      filter: drop-shadow(0 4px 6px rgba(231, 76, 60, 0.3));
    }

    .show-icon {
      opacity: 1;
      transform: translate(-50%, -50%) scale(1);
    }

    .buffer-display {
      display: flex;
      gap: 10px;
      margin-top: 30px;
    }

    .buffer-item {
      width: 40px;
      height: 40px;
      background: #ecf0f1;
      border-radius: 8px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
      transition: all 0.3s;
    }

    .buffer-item.filled {
      background: var(--buffer-color);
      color: white;
      transform: scale(1.1);
    }

    .history-panel {
      background: var(--history-bg);
      border-radius: 16px;
      padding: 20px;
      margin-top: 30px;
      width: 80%;
      max-width: 800px;
      box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
    }

    .history-title {
      margin-top: 0;
      border-bottom: 1px solid #ddd;
      padding-bottom: 10px;
    }

    .history-list {
      list-style: none;
      padding: 0;
      margin: 0;
      max-height: 300px;
      overflow-y: auto;
    }

    .history-item {
      padding: 10px 15px;
      margin-bottom: 8px;
      border-radius: 8px;
      background: white;
      box-shadow: 0 1px 3px rgba(0,0,0,0.1);
      display: flex;
      justify-content: space-between;
    }

    .history-item[data-type="producer"] {
      border-left: 4px solid var(--producer-color);
    }

    .history-item[data-type="consumer"] {
      border-left: 4px solid var(--consumer-color);
    }

    .history-time {
      color: #666;
      font-size: 0.9em;
    }

    @keyframes pulse {
      0% { transform: scale(1); }
      50% { transform: scale(1.05); }
      100% { transform: scale(1); }
    }
  </style>
</head>
<body>
<h1>生产者消费者问题</h1>

<div class="dashboard">
  <div class="status-card producer" id="producer">
    <div class="status-header">生产者状态</div>
    <div class="status-content">
      <div class="status-text">等待中</div>
      <img src="producer.png" class="action-icon" alt="生产图标">
    </div>
  </div>

  <div class="status-card consumer" id="consumer">
    <div class="status-header">消费者状态</div>
    <div class="status-content">
      <div class="status-text">等待中</div>
      <img src="consumer.png" class="action-icon" alt="消费图标">
    </div>
  </div>
</div>

<div class="buffer-display" id="bufferDisplay"></div>

<div class="history-panel">
  <h3 class="history-title">操作历史记录</h3>
  <ul class="history-list" id="historyList"></ul>
</div>

<script>
  class PCProblem {
    constructor() {
      this.buffer = [];
      this.MAX_SIZE = 5;
      this.isProducing = false;
      this.isConsuming = false;
      this.history = [];
      this.startTime = Date.now();
      this.initBufferDisplay();
      this.startSimulation();
    }

    initBufferDisplay() {
      const container = document.getElementById('bufferDisplay');
      for (let i = 0; i < this.MAX_SIZE; i++) {
        const item = document.createElement('div');
        item.className = 'buffer-item';
        container.appendChild(item);
      }
    }

    async startSimulation() {
      this.producer();
      this.consumer();
    }

    async producer() {
      while (true) {
        if (!this.isProducing && this.buffer.length < this.MAX_SIZE) {
          this.isProducing = true;
          await this.performProduction();
          this.isProducing = false;
        }
        await this.delay(1000 + Math.random() * 2000);
      }
    }

    async consumer() {
      while (true) {
        if (!this.isConsuming && this.buffer.length > 0) {
          this.isConsuming = true;
          await this.performConsumption();
          this.isConsuming = false;
        }
        await this.delay(1000 + Math.random() * 2000);
      }
    }

    async performProduction() {
      const item = Math.floor(Math.random() * 100);
      this.showAction('producer', `生产了 ${item}`);
      this.buffer.push(item);
      this.updateBufferDisplay();
      await this.delay(800); // 生产耗时

      // 记录历史
      this.addHistory('producer', `生产了 ${item}`, this.buffer.length);
    }

    async performConsumption() {
      const item = this.buffer.shift();
      this.showAction('consumer', `消费了 ${item}`);
      this.updateBufferDisplay();
      await this.delay(800); // 消费耗时

      // 记录历史
      this.addHistory('consumer', `消费了 ${item}`, this.buffer.length);
    }

    updateBufferDisplay() {
      const items = document.querySelectorAll('.buffer-item');
      items.forEach((item, index) => {
        item.classList.toggle('filled', index < this.buffer.length);
        item.textContent = index < this.buffer.length ? this.buffer[index] : '';
      });
    }

    showAction(type, text) {
      const card = document.getElementById(type);
      const icon = card.querySelector('.action-icon');
      const textElem = card.querySelector('.status-text');

      icon.classList.add('show-icon');
      textElem.textContent = text;

      setTimeout(() => {
        icon.classList.remove('show-icon');
        textElem.textContent = type === 'producer'
                ? `缓冲区：${this.buffer.length}/5`
                : `缓冲区：${this.buffer.length}/5`;
      }, 800);
    }

    addHistory(type, action, bufferSize) {
      const timestamp = new Date();
      const elapsed = Math.floor((Date.now() - this.startTime) / 1000);

      const historyEntry = {
        type,
        action,
        bufferSize,
        timestamp,
        elapsed
      };

      this.history.push(historyEntry);
      this.updateHistoryDisplay();
    }

    updateHistoryDisplay() {
      const list = document.getElementById('historyList');

      // 只保留最新的20条记录
      const recentHistory = this.history.slice(-20).reverse();

      list.innerHTML = '';

      recentHistory.forEach(entry => {
        const item = document.createElement('li');
        item.className = 'history-item';
        item.dataset.type = entry.type;
        item.innerHTML = `
          <span>${entry.action} (缓冲区: ${entry.bufferSize}/${this.MAX_SIZE})</span>
          <span class="history-time">${entry.elapsed}s</span>
        `;
        list.appendChild(item);
      });
    }

    delay(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
  }

  // 启动模拟
  new PCProblem();
</script>
</body>
</html>